﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace SpaceWolf.GameLogic
{
    public class Universe
    {
        Space_Object Planet;

        Random rnd = new Random();
        // List of all objects
        List<Space_Object> spObjects = new List<Space_Object>();
        Commander commander;

        public List<Space_Object> Objects
        {
            get
            {
                return this.spObjects;
            }
        }

        public Universe(Commander commander)
        {
            this.commander = commander;

            AddObject(commander.ship);
            
          

            //Place target
            Vector3 Position = new Vector3(30, 0 , 0);
            Ship Target = new Ship(ShipsData.Anaconda_Data, ShipOwner.Trader, Position, Matrix.CreateScale(0.1f), Vector3.Zero);
            Target.boundSphere = new BoundingSphere(Target.Location, 9);
            Target.Speed = 10;
            Target.Docked= false;
            AddObject(Target);


            Position = new Vector3(30, 50, 0);
            Space_Object Cargo = new Space_Object(ObjectTypes.Cargo, "Cargo", Position, Matrix.CreateScale(0.1f), new Vector3(0.01f, 0.003f, 0f));
            Cargo.boundSphere = new BoundingSphere(Position, 9);
            AddObject(Cargo);
        }

        public void AddPlanet(Vector3 Position)
        {
            
            Planet = new Space_Object(ObjectTypes.Planet,commander.sPlanetName, Position, 
                Matrix.Identity, new Vector3(0, 0.003f, 0));
            //Need to be repaired
            Planet.boundSphere = new BoundingSphere(Planet.Location, 50);
            lock (Objects)
            {
                for(int iCounter=0;iCounter<Objects.Count;iCounter++)
                {
                    Space_Object item = Objects[iCounter];
                    if (item.Name == commander.sPlanetName)
                        RemoveObject(item);
                }
            }
            AddObject(Planet);
        }

        /// <summary>
        /// Adds object to university
        /// </summary>
        public void AddObject(Space_Object Item)
        {
            lock (spObjects)
            {
                this.spObjects.Add(Item);
            }
        }

        /// <summary>
        /// Removes object from univesity
        /// </summary>
        private void RemoveObject(int iCount)
        {
            lock (spObjects)
            {
                this.spObjects.RemoveAt(iCount);
            }
        }
        
        private void RemoveObject(Space_Object item)
        {
            lock (spObjects)
            {
                this.spObjects.Remove(item);
            }
        }

        #region Update
        /// <summary>
        /// Update and move objects
        /// </summary>
        public void update()
        {
            for (int iCount = 0; iCount < spObjects.Count; iCount++)
            {
                //Update object
                spObjects[iCount].Update();
                
                // Update Movement & Coordinates
                if (spObjects[iCount] is Ship)
                {
                    Ship ship = (Ship)spObjects[iCount];
                    
                    //Update Ship compass
                    ship.UpdatePlanetCompass(Planet.Location);

                    //Check if ship can Dock
                    ship.AllowDocking=allow_Docking(ship);
                    
                    if (ship != commander.ship)
                        spObjects[iCount].Location += ship.Force;
                    // If ship firing
                    if (ship.State == ObjectState.Firing)
                        Check_Hit(ref ship);

                  
                }

                if (spObjects[iCount] == commander.ship.trackShip)
                {
                    Helper.Fonts.WriteText(0, 60, spObjects[iCount].Name+" " + spObjects[iCount].Energy, Microsoft.Xna.Framework.Graphics.Color.Green);
                }

                spObjects[iCount].Location -= commander.ship.Force;

                // Update collisions
                CheckCollisions(iCount, spObjects[iCount]);

                if (spObjects[iCount].Energy < 0)
                {
                    // Remove from tracking
                    for (int iTmpCount = 0; iTmpCount < spObjects.Count; iTmpCount++)
                    {
                        Space_Object Target = spObjects[iTmpCount];
                        if (Target is Ship)
                            if (spObjects[iCount] == ((Ship)Target).trackShip)
                                ((Ship)Target).trackShip = null;
                    }
                    spObjects[iCount].Blow();
                     if (spObjects[iCount].Type != ObjectTypes.Cargo)
                     {
                        Space_Object Cargo  = new Space_Object(ObjectTypes.Cargo,"Cargo", spObjects[iCount].Location, spObjects[iCount].Orientation, new Vector3(0.01f, 0.003f, 0f));
                        Cargo.boundSphere = new BoundingSphere(spObjects[iCount].Location, 9);
                        spObjects.Add(Cargo);
                     }
                    lock (spObjects)
                    {
                        spObjects.RemoveAt(iCount);
                    }
                }
            }
        }

        /// <summary>
        /// Check if ship Can be docked
        /// </summary>
        public bool allow_Docking(Ship spObject)
        {
            for (int iCount = 0; iCount < spObjects.Count; iCount++)
            {
                if (!(spObjects[iCount] is Ship))
                {
                    if (spObjects[iCount].Type == ObjectTypes.Planet ||
                        spObjects[iCount].Type == ObjectTypes.Dodec || 
                        spObjects[iCount].Type == ObjectTypes.Coriolis)
                    {
                        float Distance = spObjects[iCount].Location.Length() - spObject.Location.Length();

                        if (spObjects[iCount].Type == ObjectTypes.Planet)
                        {
                            if (Distance < 255)
                            {
                                spObject.Altitude = 255 - ((int)Distance - 100);
                            }
                            else
                                spObject.Altitude = 0;
                        }
                        
                        if (Distance < 350)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// Check collisions between objects
        /// </summary>
        private void CheckCollisions(int iStart,Space_Object spObject)
        {
            for (int iCollisionsCount = iStart; iCollisionsCount < spObjects.Count; iCollisionsCount++)
            {
                Space_Object otherObject = spObjects[iCollisionsCount];
                if (spObject != otherObject)
                {
                    if (otherObject.boundSphere.Intersects(spObject.boundSphere))
                    {
                        if (spObject is Ship)
                        {
                            Ship currentShip = (Ship)spObject;
                            if (commander.ship==currentShip && otherObject.Type == ObjectTypes.Cargo
                            && commander.total_cargo() < currentShip.CargoBay)
                            {
                                commander.current_cargo[rnd.Next(16)] += 1 + rnd.Next(10);
                                RemoveObject(iCollisionsCount);
                                continue;
                            }
                        }
                        //if (ship.type == ShipTypes.Planet)
                        //{
                        //    otherShip.Energy = 0;
                        //    continue;
                        //}
                        otherObject.Impact(spObject);
                    }
                }
            }
        }

        /// <summary>
        /// Check if Laser was hit any object
        /// </summary>
        private void Check_Hit(ref Ship ship)
        {
            for (int iCount = 0; iCount < spObjects.Count; iCount++)
            {
                Space_Object Target = spObjects[iCount];
                if(Target is Ship)
                if (ship != (Ship)Target)
                {
                    for (int i = 0; i < 20; i++)
                        if (ship.Laserbolts.bolt[i].alive)
                        {
                            // HIT !
                            if (ship.Laserbolts.bolt[i].boundSphere.Contains(Target.boundSphere) != ContainmentType.Disjoint)
                            {
                                ((Ship)Target).Damage(ship.CurrentLaser.HitPower, Math.Abs(ship.Direction.Z - ((Ship)Target).Direction.Z) < 0);

                                Laserbolt.iBolts--;
                                ship.Laserbolts.bolt[i].alive = false;

                                Target.State = ObjectState.Angry;

                                if (Target.Type != ObjectTypes.Coriolis &&
                                    Target.Type != ObjectTypes.Dodec &&
                                    Target.Type != ObjectTypes.Planet)
                                {
                                    //TargetShip.speed = TargetShip.data.MaxSpeed;
                                    ((Ship)Target).trackShip = ship;
                                }
                            }
                        }
                }
            }
        }
        #endregion
    }
}
